(define pega-nome
  (lambda (carta)
    (car carta)))

(define carta->valor
  (lambda (carta)
    (case carta
      ((2 3 4 5 6 7 8) carta)
      ((j) 11)
      ((q) 12)
      ((k) 13)
      ((a) 14)
      (else (error "Carta não existe")))))


(define maior-carta
  (lambda (hand)
    (let repete ((cartas hand) (maior 0))
      (if (null? (cartas))
          maior
          (let ((valor (carta->valor (pega-nome (car hand)))))
            (if (> valor maior)
                (repete (cdr cartas) valor)
                (repete (cdr cartas) maior)))))))

;;Número aleatório entre 0 e k:
;; 
(define linear-congruencial
  (lambda (x a b m)
    (modulo (+ (* a x) b) m)))

(define next-random
  (lambda (x)
    (linear-congruencial x
                         1103515245
                         12345
                         (expt 2 32))))
(define next-integer-random
  (lambda (x n)
    (let ((m (/ (expt 2 32 n))))
      (let again ((r (next-random x)))
        (if (> r m)
            (again ((r (next-random r))))
            (floor (/ r m)))))))

;;letrec
;; 
(define list-ref-1
  (lambda (lst n)
    (cond ((not (and (list? lst)
                     (integer? n)))
           (error "list-ref: need a list and an integer"))
          ((negative? n) (error "n<0"))
          ((>= n (length lst)) (error "n> max"))
          ((= n 0) (car lst))
          (else
           (list-ref-1 (cdr lst) (- n 1))))))

(list-ref-1 (list 'a 'b 'c) 2)

(define list-ref
  (lambda (lst n)
    (letrec ((list-ref-aux (lambda (lst n)
                             (if (= n 0)
                                 (car lst))
                             (list-ref-aux (cdr lst) (- n 1)))))
      (cond ((not (and (list? lst)
                       (integer? n)))
             (error "list-ref: need a list and an integer"))
            
            ((negative? n) (error "n<0"))
            ((>= n (- (length lst) -1)) (error "n>max"))
            (else (list-ref-aux lst n))))))

(list-ref '(a b c) 1)

(define list-map
  (lambda (funcao lista)
    (if (null? lista)
        lista
        (cons (funcao (car lista))
              (list-map funcao (cdr lista))))))

(list-map - '(0 1 2 -3))

(map expt '(1 3 2)
     '(2 3 4))

(define list-reduce
  (lambda (proc default lista)
    
    (letrec ((really-reduce
              (lambda (proc lista)
                (if (= 1 (length lista))
                    (car lista)
                    (proc (car lista)
                          (really-reduce proc
                                         (cdr lista)))))))
      (if (null? lista)
          default
          (really-reduce proc lista)))))

(list-reduce * -1 '(10 20 30))


